
local LUtil = require 'packages/lingling/utility/_base'

local U = require "packages/utility/utility"

--斗地主专属技能
local bahu = fk.CreateTriggerSkill{
  name = "lingling_lord__bahu&",
  anim_type = "drawcard",
  frequency = Skill.Compulsory,
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and player:usedSkillTimes(self.name, Player.HistoryRound) == 0
  end,
  on_use = function(self, event, target, player, data)
    player:drawCards(2, self.name)
  end,
}
local bahu_targetmod = fk.CreateTargetModSkill{
  name = "#lingling_lord__bahu&_targetmod",
  residue_func = function(self, player, skill, scope)
    if player:hasSkill(bahu) and skill.trueName == "slash_skill" and scope == Player.HistoryPhase then
      return 1
    end
  end,
}
bahu:addRelatedSkill(bahu_targetmod)
Fk:addSkill(bahu)
Fk:loadTranslationTable{
  ["lingling_lord__bahu&"] = "跋扈",
  [":lingling_lord__bahu&"] = "锁定技，回合开始时，你摸两张牌；出牌阶段，你可以多使用一张【杀】。",
}

local chengqiang = fk.CreateTriggerSkill{
  name = "lingling_lord__chengqiang&",
  anim_type = "defensive",
  frequency = Skill.Compulsory,
  events = {fk.GameStart},
  can_trigger = function (self, event, target, player, data)
    return player:hasSkill(self) and player.role == "lord"
  end,
  on_use = function (self, event, target, player, data)
    player.room:changeShield(player, 3)
  end,

  refresh_events = {fk.HpChanged, fk.Damaged, fk.Death},
  can_refresh = function (self, event, target, player, data)
    return player:usedSkillTimes(self.name, Player.HistoryGame) > 0
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.HpChanged and target == player then
      if target and data.reason == "damage" and data.shield_lost > 0 then
        local e = room.logic:getCurrentEvent():findParent(GameEvent.Damage)
        if e then
          local damage = e.data[1]
          damage.extra_data = damage.extra_data or {}
          damage.extra_data.shield_lost = data.shield_lost
        end
      end
    elseif event == fk.Damaged and target == player then
      if data.extra_data and (data.extra_data.shield_lost or 0) > 0 then
        room.logic:getCurrentEvent():shutdown()
      end
    elseif event == fk.Death then
      room:changeShield(player, -3)
    end
  end,
}
Fk:addSkill(chengqiang)
Fk:loadTranslationTable{
  ["lingling_lord__chengqiang&"] = "城墙",
  [":lingling_lord__chengqiang&"] = "游戏开始时获得3点护甲（不触发受到伤害相关的技能），当一名其他角色死亡后失去这些护甲。",
}

local jiayi = fk.CreateViewAsSkill{
  name = "lingling_lord__jiayi&",
  anim_type = "control",
  prompt = "#lingling_lord__jiayi&",
  card_filter = Util.FalseFunc,
  view_as = function(self, player, cards)
    local card = Fk:cloneCard("sincere_treat")
    card.skillName = "lingling_lord__jiayi"
    return card
  end,
  enabled_at_play = function (self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,

  on_acquire = function (self, player, is_start)
    local room = player.room
    local targets = {}
    room.logic:getActualDamageEvents(1, function(e)
      local damage = e.data[1]
      if damage.from == player then
        table.insertIfNeed(targets, damage.to.id)
      end
    end, Player.HistoryGame)
    room:setPlayerMark(player, self.name, targets)
  end,
}
local jiayi_prohibit = fk.CreateProhibitSkill{
  name = "#lingling_lord__jiayi&_prohibit",
  is_prohibited = function(self, from, to, card)
    return table.contains(card.skillNames, "lingling_lord__jiayi") and
      table.contains(from:getTableMark("lingling_lord__jiayi"), to.id)
  end,
}
local jiayi_trigger = fk.CreateTriggerSkill{
  name = "#lingling_lord__jiayi&_trigger",

  refresh_events = {fk.Damage},
  can_refresh = function (self, event, target, player, data)
    return target == player and player:hasSkill(self, true)
  end,
  on_refresh = function (self, event, target, player, data)
    player.room:addTableMark(player, "lingling_lord__jiayi", data.to.id)
  end,
}
jiayi:addRelatedSkill(jiayi_prohibit)
jiayi:addRelatedSkill(jiayi_trigger)
Fk:addSkill(jiayi)
Fk:loadTranslationTable{
  ["lingling_lord__jiayi&"] = "假意",
  [":lingling_lord__jiayi&"] = "出牌阶段限一次，你可以视为对一名你未对其造成过伤害的其他角色使用【推心置腹】。",
  ["#lingling_lord__jiayi&"] = "假意：视为对一名未对其造成过伤害的角色使用【推心置腹】",
}

local fenbing = fk.CreateTriggerSkill{
  name = "lingling_lord__fenbing&",
  anim_type = "offensive",
  events = {fk.AfterCardTargetDeclared},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.card.trueName == "slash" and
      #player.room:getUseExtraTargets(data) > 0 and player:usedSkillTimes(self.name, Player.HistoryTurn) == 0 and
      player.room:getTag("RoundCount") % 2 < 3
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local to = room:askForChoosePlayers(player, room:getUseExtraTargets(data), 1, 1,
      "#lingling_lord__fenbing-invoke:::"..data.card:toLogString(), self.name, true)
    if #to > 0 then
      self.cost_data = {tos = to}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    table.insert(data.tos, self.cost_data.tos)
  end,
}
Fk:addSkill(fenbing)
Fk:loadTranslationTable{
  ["lingling_lord__fenbing&"] = "分兵",
  [":lingling_lord__fenbing&"] = "前三轮内，每回合限一次，当你使用【杀】指定目标时，你可以额外指定一名目标。",
  ["#lingling_lord__fenbing-invoke"] = "分兵：你可以为%arg额外指定一个目标",
}

---@param player ServerPlayer 获得技能的角色（用于判断hasSkill）
---@param num integer 获得技能数
---@return string[] @返回获得技能名列表，可能为空
LUtil.GetRandomSkills = function (player, num)
  num = num or 1
  local skills = {}
  for _, general in pairs(Fk.generals) do
    if not general.hidden and not general.total_hidden then
      table.insertTableIfNeed(skills, general:getSkillNameList(true))
    end
  end
  skills = table.filter(skills, function (s)
    return not player:hasSkill(s, true)
  end)
  if #skills > 0 then
    return table.random(skills, num)
  end
end

---@param player ServerPlayer 获得预演回合的角色
---@param skillName string 额外回合技能名
LUtil.GainRehearsalTurn = function (player, skillName)
  skillName = skillName or "game_rule"
  local room = player.room
  room:setPlayerMark(player, "@@lingling__RehearsalTurn", 1)
  player:gainAnExtraTurn(true, "lingling__RehearsalTurn")
end
Fk:loadTranslationTable{
  ["@@lingling__RehearsalTurn"] = "预演回合",
}

local RehearsalTurn = fk.CreateTriggerSkill{
  name = "#RehearsalTurn",
  global = true,
  priority = 0.1,
  mute = true,
  events = {fk.TurnEnd},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:getMark("@@lingling__RehearsalTurn") ~= 0
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local hp_record = player:getMark("lingling__RehearsalTurn")
    if type(hp_record) ~= "table" then return end
    for _, p in ipairs(room:getAlivePlayers()) do
      local p_record = table.find(hp_record, function (sub_record)
        return #sub_record == 2 and sub_record[1] == p.id
      end)
      if p_record then
        p.hp = math.min(p.maxHp, p_record[2])
        room:broadcastProperty(p, "hp")
      end
    end
  end,

  refresh_events = {fk.TurnStart, fk.AfterTurnEnd},
  can_refresh = function(self, event, target, player, data)
    if target == player then
      if event == fk.TurnStart then
        local turn_event = player.room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
        return turn_event and turn_event.data[1] == player and turn_event.data[2].reason == "lingling__RehearsalTurn"
      elseif event == fk.AfterTurnEnd then
        return true
      end
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    if event == fk.TurnStart then
      local hp_record = {}
      for _, p in ipairs(room.alive_players) do
        table.insert(hp_record, {p.id, p.hp})
      end
      room:setPlayerMark(player, "lingling__RehearsalTurn", hp_record)
    elseif event == fk.AfterTurnEnd then
      room:setPlayerMark(player, "lingling__RehearsalTurn", 0)
      room:setPlayerMark(player, "@@lingling__RehearsalTurn", 0)
    end
  end,
}
Fk:addSkill(RehearsalTurn)

local Global = fk.CreateTriggerSkill{
  name = "#LingGlobal",
  global = true,
  priority = 2,

  refresh_events = {fk.AfterCardsMove, fk.AfterDrawPileShuffle, fk.AfterTurnEnd,
    fk.GamePrepared, fk.EventAcquireSkill, fk.EventLoseSkill,
    fk.DrawInitialCards, fk.AfterDrawInitialCards, fk.TurnStart, fk.Death,
    --fk.SkillEffect
  },
  can_refresh = function(self, event, target, player, data)
    if player.seat == 1 then
      if event == fk.GamePrepared then
        return not table.contains(player.room.disabled_packs, "ling_cards")
      elseif event == fk.DrawInitialCards then
        return #player.room.players > 6 and player.room:isGameMode("role_mode")
      elseif event == fk.TurnStart then
        return player.room:getTag("RoundCount") == 1 and target.seat > 6 and player.room:isGameMode("role_mode")
      elseif event == fk.Death then
        return player.room:isGameMode("1v2_mode")
      --elseif event == fk.SkillEffect then
      --  return data.name == "#m_1v2_rule"
      else
        return true
      end
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    --七八号位增益
    if event == fk.DrawInitialCards then
      if target.seat == 7 then
        data.num = data.num + 1
      elseif target.seat == 8 then
        data.num = data.num + 2
      end
    elseif event == fk.TurnStart then
      room:handleAddLoseSkills(target, "m_feiyang", nil, false, true)
      room.logic:getCurrentEvent():findParent(GameEvent.Turn, true):addCleaner(function()
        room:handleAddLoseSkills(target, "-m_feiyang", nil, false, true)
      end)
    elseif event == fk.Death then
      if room:isGameMode("1v2_mode") then
        local lord = room:getLord() or room.players[1]
        room:handleAddLoseSkills(lord, "-lingling_lord__bahu&|-m_feiyang", nil, true, false)
      end
    --[[elseif event == fk.SkillEffect then
      local lord = room:getLord() or room.players[1]
      local choices = {"m_1v2_draw2", "Cancel"}
      if lord:isWounded() then
        table.insert(choices, 2, "m_1v2_heal")
      end
      local choice = room:askForChoice(lord, choices, "#m_1v2_rule")
      if choice == "m_1v2_draw2" then
        lord:drawCards(2, "#m_1v2_rule")
      else
        room:recover{ who = lord, num = 1, skillName = "#m_1v2_rule" }
      end
      local e = room.logic:getCurrentEvent()
      e:shutdown()]]--
    else
      if event == fk.GamePrepared then
        --地主buff
        if room:isGameMode("1v2_mode") then
          local lord = room:getLord() or room.players[1]
          room:handleAddLoseSkills(lord, "-m_bahu|lingling_lord__bahu&", nil, false, false)
          local result = player.room:askForCustomDialog(player, "1v2_mode",
            "packages/utility/qml/ChooseSkillBox.qml", {
              {
                "lingling_lord__chengqiang&",
                "lingling_lord__jiayi&",
                "lingling_lord__fenbing&"
              }, 0, 1, "#lingling_lord_skill-choice", {},
            })
          if result ~= "" and #json.decode(result) > 0 then
            room:handleAddLoseSkills(player, json.decode(result)[1], nil, true, false)
          else
            room:handleAddLoseSkills(player, "lingling_lord__chengqiang&", nil, true, false)
          end
        end
        for i = #room.draw_pile, 1, -1 do
          local id = room.draw_pile[i]
          local card = Fk:getCardById(id)
          --雌雄双股剑替换
          if card.name == "double_swords" then
            table.insert(room.void, id)
            room:setCardArea(id, Card.Void, nil)
            local new_card = room:printCard("ling__double_swords", Fk:getCardById(id).suit, Fk:getCardById(id).number)
            room.draw_pile[i] = new_card.id
            room:setCardArea(new_card.id, Card.DrawPile, nil)
          --方天画戟替换
          elseif card.name == "halberd" then
            table.insert(room.void, id)
            room:setCardArea(id, Card.Void, nil)
            local new_card = room:printCard("ling__modao", Fk:getCardById(id).suit, Fk:getCardById(id).number)
            room.draw_pile[i] = new_card.id
            room:setCardArea(new_card.id, Card.DrawPile, nil)
          --朱雀羽扇替换
          elseif card.name == "fan" then
            table.insert(room.void, id)
            room:setCardArea(id, Card.Void, nil)
            local new_card = room:printCard("ling__fire_gun", Fk:getCardById(id).suit, Fk:getCardById(id).number)
            room.draw_pile[i] = new_card.id
            room:setCardArea(new_card.id, Card.DrawPile, nil)
          --暂时移除乐不思蜀
          elseif card.name == "indulgence" then
            local tag = room.tag["ling_indulgence"] or {}
            table.insert(room.void, id)
            room:setTag("ling_indulgence", tag)
            table.insert(tag, id)
            room:setCardArea(id, Card.Void, nil)
            table.remove(room.draw_pile, i)
          end
        end
        room:syncDrawPile()
        room:doBroadcastNotify("UpdateDrawPile", tostring(#room.draw_pile))
      elseif event == fk.AfterDrawInitialCards then
        --乐不思蜀洗至牌堆后半
        local tag = room.tag["ling_indulgence"] or {}
        for _, id in ipairs(tag) do
          if room:getCardArea(id) == Card.Void then
            table.removeOne(room.void, id)
            table.insert(room.draw_pile, math.random(math.min(#room.draw_pile // 2, 50), #room.draw_pile), id)
            room:setCardArea(id, Card.DrawPile, nil)
          end
        end
        room:setTag("ling_indulgence", nil)
        room:syncDrawPile()
        room:doBroadcastNotify("UpdateDrawPile", tostring(#room.draw_pile))
      end
      --中央区显示相关
      if event == fk.EventLoseSkill then
        room:setBanner("@$CenterArea", nil)
      elseif event == fk.AfterTurnEnd then
        room:setBanner("@$CenterArea", {})
      else
        local cards = {}
        room.logic:getEventsOfScope(GameEvent.MoveCards, 1, function(e)
          for _, move in ipairs(e.data) do
            if move.toArea == Card.DiscardPile then
              for _, info in ipairs(move.moveInfo) do
                table.insertIfNeed(cards, info.cardId)
              end
            end
          end
        end, Player.HistoryTurn)
        cards = table.filter(cards, function (id)
          local card = Fk:getCardById(id)
          return table.contains(room.discard_pile, id) and
            table.every(MarkEnum.TempMarkSuffix, function (suffix)
            return card:getMark("RemoveCenterCards"..suffix) == 0
          end)
        end)
        room:setBanner("@$CenterArea", cards)
      end
    end
  end,
}
Fk:addSkill(Global)
Fk:loadTranslationTable{
  ["#lingling_lord_skill-choice"] = "选择获得其中一项技能",
  ["@$CenterArea"] = "中央区",
  ["$CenterArea"] = "中央区",
}

return LUtil
